package com.users.rn.rncommon.util;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.text.TextUtils;

import com.users.rn.common.init.ALHReactNativeInit;
import com.users.rn.common.plugin.PluginHelper;
import com.facebook.react.bridge.ReactContext;
import com.users.rn.rncommon.model.PluginInfo;
import com.users.rn.rncommon.model.SchemeModule;
import com.users.rn.rncommon.network.utils.SharePreferenceUtils;
import com.users.rn.rncommon.plugin.PluginInformation;
import com.users.rn.rncommon.ui.RNActivity;
import com.ylkj.libcommon.utils.ALog;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

/**
 * @Description:
 * @Author: bluce
 * @Date: 2020/12/3 11:05
 */
public final class ReactUtils {

    public static boolean checkAssetsFileExist(Context ctx, String assetsPath) {
        if (ctx != null && !TextUtils.isEmpty(assetsPath)) {
            try {
                String path = assetsPath;
                if (assetsPath.startsWith(ReactConst.RN_ASSETS_PREFIX)) {
                    path = assetsPath.substring(ReactConst.RN_ASSETS_PREFIX.length());
                }
                ctx.getAssets().open(path);
                return true;
            } catch (IOException e) {
                logError(e.toString());
            }
        }
        return false;
    }

    /**
     * 判断是否是灰度环境
     *
     * @return
     */
    public static Boolean isGrey(Context context) {
        return false;//ServiceManager.get().getGreyService().isGrey(context);
    }

    /**
     * 返回具体环境值
     * 线上环境: nogrey
     * 灰度环境：grey1, grey2, grey3, grey4....
     *
     * @return
     */
    public static String getGreyStatus(Context context) {
        return "grey1";//ServiceManager.get().getGreyService().getGreyStatus(context);
    }

    /**
     * 确认是否支持pluginId
     *
     * @param pluginId pluginId
     * @return 结果
     */
    public static boolean checkPluginIdExist(String pluginId, List<PluginInformation> pluginInfos) {
        if (pluginInfos == null || pluginInfos.isEmpty()) {
            return false;
        }
        boolean result = false;
        for (PluginInformation pluginInfo : pluginInfos) {
            if (pluginId.equalsIgnoreCase(pluginInfo.getPluginName())) {
                result = true;
                break;
            }
        }
        return result;
    }

    public static boolean checkSDCardFileExist(String sdPath) {
        if (!TextUtils.isEmpty(sdPath)) {
            File sdFile = new File(sdPath);
            return sdFile.exists();
        }
        return false;
    }

    public static void logError(String msg) {
//        if (!TextUtils.isEmpty(msg)) {
//            if (BuildConfig.DEBUG) {
//                String callerInformation = getCallerInformation();
//                callerInformation += ", time=" + System.currentTimeMillis();
//                Log.e(ReactConst.TAG, TextUtils.isEmpty(callerInformation) ? msg : msg + ", " + callerInformation);
//            } else {
        ALog.e(ReactConst.TAG, msg);
//            }
//            writeLogToFile(msg);
//        }
    }

    /**
     * 获取调用者的来源信息
     *
     * @return
     */
    private static String getCallerInformation() {
        StringBuilder sb = new StringBuilder();
        try {
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            //4 是根据Thread.currentThread().getStackTrace();这行代码调用的方法层级决定的，不要轻易修改。
            if (stackTrace.length > 4) {
                String logTag = "%s.%s(L:%d)";
                StackTraceElement element = stackTrace[4];
                sb.append(String.format(Locale.ENGLISH, logTag, element.getFileName(), element.getMethodName(), element.getLineNumber()));
                if (stackTrace.length > 5) {
                    sb.append(", ");
                    StackTraceElement e = stackTrace[5];
                    sb.append(String.format(Locale.ENGLISH, logTag, e.getFileName(), e.getMethodName(), e.getLineNumber()));
                }
                return sb.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static void log(String msg) {
        if (!TextUtils.isEmpty(msg)) {
            String callerInformation = getCallerInformation();
            callerInformation += ", time=" + System.currentTimeMillis();
            ALog.i(ReactConst.TAG, TextUtils.isEmpty(callerInformation) ? msg : msg + ", " + callerInformation);
//            writeLogToFile(msg);
        }
    }


    public static void setDebugInfo(Context context, RNDebugUtils.RNDebugModel model) {
        SharePreferenceUtils.edit(context, ReactConst.RN_TYPE).putBoolean(model.pluginId, model.isEnable).apply();
    }

    public static boolean getDebugPluginId(Context context, String pluginId) {
        if (context == null) {
            return false;
        }
        return SharePreferenceUtils.getBoolean(context, ReactConst.RN_TYPE, pluginId);
    }

    /**
     * 获得测试环境,线上环境变量
     *
     * @param context 上下文
     * @return 如果是线上直接是打开，如果非线上看flag值
     */
    public static boolean getEventFlag(Context context) {
        return true;
    }

    /**
     * pajk_rn_runningtime_exception - 打点
     *
     * @param ctx
     * @param info
     * @param reason
     */
    public static void eventErrorBundle(Context ctx, PluginInfo info, String reason) {
        if (ctx != null && info != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("reason", reason);
            map.put("bundleInfo", info.toString());
//            ServiceManager.get().getAnalysisService().onEventMap(ctx, ReactConst.PAJK_RN_RUNNINGTIME_EXCEPTION, null, map);
        }
    }

    public static void eventBizBundle(Context ctx, PluginInfo pluginInfo, String reason) {
        if (ctx != null && pluginInfo != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("reason", reason);
            map.put("bundleInfo", pluginInfo.toString());
//            ServiceManager.get().getAnalysisService().onEventMap(ctx, ReactConst.PAJK_RN_BIZ_BUNDLE_FAILURE, null, map);
        }
    }

    /**
     * JsonString -> Bundle
     *
     * @param params
     * @return
     */
    public static Bundle jsonStringToBundle(String params) {
        Bundle bundle = new Bundle();
        if (!TextUtils.isEmpty(params)) {
            try {
                JSONObject jsonObject = new JSONObject(params);
                Iterator<String> keys = jsonObject.keys();
                while (keys.hasNext()) {
                    String k = keys.next();
                    try {
                        String string = jsonObject.optString(k);
                        bundle.putString(k, string);
                    } catch (Exception e) {
                        bundle.putString(k, "");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return bundle;
    }

    /**
     * 新版转换，将二层、三层参数转成JSONObject给js
     *
     * @param params
     * @return
     */
    public static Bundle jsonStringToBundleNew(String params) {
        Bundle bundle = new Bundle();
        if (!TextUtils.isEmpty(params)) {
            try {
                JSONObject jsonObject = new JSONObject(params);
                Iterator<String> keys = jsonObject.keys();
                while (keys.hasNext()) {
                    String k = keys.next();
                    Object value = jsonObject.get(k);
                    if (value == null) {
                        bundle.putBundle(k, null);
                    } else if (value instanceof JSONObject) {
                        JSONObject json = (JSONObject) value;
                        bundle.putBundle(k, jsonStringToBundleNew(json.toString()));
                    } else if (value instanceof JSONArray) {
                        //不处理
                        //因为bundle不支持ArrayList<Object>
                        JSONArray array = (JSONArray) value;
                        bundle.putString(k, array.toString());
                    } else if (value instanceof String) {
                        bundle.putString(k, String.valueOf(value));
                    } else if (value instanceof Boolean) {
                        bundle.putBoolean(k, (Boolean) value);
                    } else if (value instanceof Integer) {
                        bundle.putInt(k, (Integer) value);
                    } else if (value instanceof Long) {
                        bundle.putLong(k, (Long) value);
                    } else if (value instanceof Double) {
                        bundle.putDouble(k, (Double) value);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return bundle;
    }

    public static void openRnPageView(Context context, SchemeModule model) {
        openRnPageView(context, getRnIntent(context, model));
    }

    public static void openRnPageView(Context context, Intent intent) {
        if (intent == null || context == null) {
            return;
        }
        if (context instanceof ReactContext) {
            ReactContext rc = (ReactContext) context;
            Activity currentActivity = rc.getCurrentActivity();
            if (currentActivity != null) {
                currentActivity.startActivity(intent);
                return;
            }
        }
        if (context instanceof Activity) {
            Activity activity = (Activity) context;
            activity.startActivity(intent);
        } else {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }

    public static Intent getRnIntent(Context ctx, SchemeModule model) {
        return getRnIntent(ctx, model, true);
    }

    public static Intent getRnIntent(Context ctx, SchemeModule model, boolean eventFlag) {
        Intent intent = null;
        if (ctx != null && model != null && model.isModelValid()) {
            String launchMode = model.getLaunchmode();
            //默认就是standard模式启动
            Class<? extends RNActivity> clazz = RNActivity.class;
//            if (ReactConst.LAUNCH_MODE_SINGLE_TOP.equalsIgnoreCase(launchMode)) {
//                clazz = RnSingleTopActivity.class;
//            } else if (ReactConst.LAUNCH_MODE_SINGLE_INSTANCE.equalsIgnoreCase(launchMode)) {
//                clazz = RnSingleInstanceActivity.class;
//            } else if (ReactConst.LAUNCH_MODE_SINGLE_TASK.equalsIgnoreCase(launchMode)) {
//                clazz = RnSingleTaskActivity.class;
//            }
            intent = RNActivity.getIntent(ctx, clazz, model.getPluginid(), model.getModuleid(), model.getComponentname(), model.getParams());
        }
        if (intent != null) {
            intent.putExtra(ReactConst.INTENT_KEY_EVENT_FLAG, eventFlag);
        }
        return intent;
    }

    public static boolean checkJsBundleFileExistFromAll(Context context, String pluginId) {
        String ip = getDebugIp(context, pluginId);
        if (!TextUtils.isEmpty(ip)) {
            RNLogger.i("checkJsBundleFileExistFromAll pluginId:" + pluginId + " ,debugIp:" + ip + " ,context" + context);
            return true;
        } else {
            boolean existFromAssets = checkJsBundleFileExistFromAssets(context, pluginId);
            boolean existFromSDCard = checkJsBundleFileExistFromSD(context, pluginId);
            RNLogger.i("checkJsBundleFileExistFromAll pluginId:" + pluginId + " ,existFromAssets:" + existFromAssets + " ,existFromSDCard:" + existFromSDCard + " ,context:" + context);
            return existFromAssets || existFromSDCard;
        }
    }

    public static String getDebugIp(Context context, String pluginId) {
        if (context != null && !TextUtils.isEmpty(pluginId)) {
            boolean isProdLevel = ALHReactNativeInit.INSTANCE.getInitInterface().isTestEnv();
            return isProdLevel ? "" : RNDebugUtils.getDebugIp(context, pluginId);
        } else {
            return "";
        }
    }

    /**
     * 检查assets下是否存在*.jsbundle文件
     *
     * @param context
     * @param pluginId
     * @return
     */
    public static boolean checkJsBundleFileExistFromAssets(Context context, String pluginId) {
        if (context == null || TextUtils.isEmpty(pluginId)) {
            RNLogger.e("checkJsBundleFileExistFromAssets false pluginId:" + pluginId);
            return false;
        }
        try {
            AssetManager assets = context.getApplicationContext().getResources().getAssets();
            if (assets != null) {
                //返回的是assets下文件的相对路径，例如"headline/index.jsbundle"
                String[] files = assets.list(pluginId);
                for (int i = 0; i < (files == null ? 0 : files.length); i++) {
                    String file = files[i];
                    if (!TextUtils.isEmpty(file) && file.endsWith(".jsbundle")) {
                        RNLogger.e("checkJsBundleFileExistFromAssets true pluginId:" + pluginId);
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            RNLogger.e("checkJsBundleFileExistFromSD Exception:" + e.toString());
        }
        return false;
    }

    /**
     * 检查sd下是否存在*.jsbundle文件
     *
     * @param context
     * @param pluginId
     * @return
     */
    public static boolean checkJsBundleFileExistFromSD(Context context, String pluginId) {
        if (context == null || TextUtils.isEmpty(pluginId)) {
            RNLogger.e("checkJsBundleFileExistFromSD false context null or pluginId:" + pluginId);
            return false;
        }
        try {
            String sdVersion = String.valueOf(PluginHelper.INSTANCE.getPluginVersion(pluginId));
            String sdPath;

            if (!TextUtils.isEmpty(sdVersion) && !sdVersion.equalsIgnoreCase("-1")) {
                File pluginFile = context.getExternalFilesDir("plugin");
                if (pluginFile == null || !pluginFile.exists()) {
                    RNLogger.e("checkJsBundleFileExistFromSD false pluginFile null or pluginFile not exist, pluginId:" + pluginId);
                    return false;
                }
//                if (isGrey(context)) {
//                    sdPath = pluginFile.getAbsolutePath().concat(File.separator + getGreyStatus(context) + File.separator + pluginId + File.separator + sdVersion);
//                } else {
                sdPath = pluginFile.getAbsolutePath().concat(File.separator + pluginId + File.separator + sdVersion);
//                }
                if (TextUtils.isEmpty(sdPath)) {
                    RNLogger.e("checkJsBundleFileExistFromSD false sdPath is null, pluginId:" + pluginId);
                    return false;
                }
                File sdFile = new File(sdPath);
                if (!sdFile.exists()) {
                    RNLogger.e("checkJsBundleFileExistFromSD false sdFile not exist, pluginId:" + pluginId);
                    return false;
                }
                int fileNumber = sdFile.list().length;
                if (fileNumber > 1) {
                    File[] files = sdFile.listFiles();
                    for (int i = 0; i < (files == null ? 0 : files.length); i++) {
                        File file = files[i];
                        if (file != null && file.isFile() && file.getName().endsWith(".jsbundle")) {
                            RNLogger.e("checkJsBundleFileExistFromSD true pluginId:" + pluginId + " ,filename:" + file.getName());
                            return true;
                        }
                    }
                } else {
                    RNLogger.e("checkJsBundleFileExistFromSD false fileNumber <= 1, pluginId:" + pluginId);
                }
            }
        } catch (Exception e) {
            RNLogger.e("checkJsBundleFileExistFromSD Exception:" + e.toString());
        }
        return false;
    }

    public static void log2FileRn(String s) {
    }
}
